package memo

import "sync"

const (
	cPoolSizeSmall  = 512   // Underlying array size of small buffer
	cPoolSizeMedium = 4096  // Underlying array size of medium buffer
	cPoolSizeLarge  = 65536 // Underlying array size of large buffer
)

var poolSmall = &sync.Pool{
	New: func() any {
		b := [cPoolSizeSmall]byte{}
		return &b
	},
}

var poolMedium = &sync.Pool{
	New: func() any {
		b := [cPoolSizeMedium]byte{}
		return &b
	},
}

var poolLarge = &sync.Pool{
	New: func() any {
		b := [cPoolSizeLarge]byte{}
		return &b
	},
}

// return len = 0
func PoolGet_len0(sz int) []byte {
	switch {
	case sz <= cPoolSizeSmall:
		return poolSmall.Get().(*[cPoolSizeSmall]byte)[:0]
	case sz <= cPoolSizeMedium:
		return poolMedium.Get().(*[cPoolSizeMedium]byte)[:0]
	default:
		return poolLarge.Get().(*[cPoolSizeLarge]byte)[:0]
	}
}

// return len = sz
func PoolGet_sz(sz int) []byte {
	switch {
	case sz <= cPoolSizeSmall:
		return poolSmall.Get().(*[cPoolSizeSmall]byte)[:sz]
	case sz <= cPoolSizeMedium:
		return poolMedium.Get().(*[cPoolSizeMedium]byte)[:sz]
	default:
		return poolLarge.Get().(*[cPoolSizeLarge]byte)[:sz]
	}
}

// return len = cap
func PoolGet_cap(sz int) []byte {
	switch {
	case sz <= cPoolSizeSmall:
		return poolSmall.Get().(*[cPoolSizeSmall]byte)[:]
	case sz <= cPoolSizeMedium:
		return poolMedium.Get().(*[cPoolSizeMedium]byte)[:]
	default:
		return poolLarge.Get().(*[cPoolSizeLarge]byte)[:]
	}
}

func PoolPut(b []byte) {
	switch cap(b) {
	case cPoolSizeSmall:
		b := (*[cPoolSizeSmall]byte)(b[0:cPoolSizeSmall])
		poolSmall.Put(b)
	case cPoolSizeMedium:
		b := (*[cPoolSizeMedium]byte)(b[0:cPoolSizeMedium])
		poolMedium.Put(b)
	case cPoolSizeLarge:
		b := (*[cPoolSizeLarge]byte)(b[0:cPoolSizeLarge])
		poolLarge.Put(b)
	default:
	}
}

func PoolPut_clr(b *[]byte) {
	PoolPut(*b)
	b = nil
}
